import type { ApiEndpoint, CmsContext, CmsFieldTypePlugins, CmsModel } from "~/types/index.js";
import type { ICmsGraphQLSchemaPlugin } from "~/plugins/index.js";
import { createCmsGraphQLSchemaPlugin } from "~/plugins/index.js";
import type { IGraphQLSchemaPlugin } from "@webiny/handler-graphql";
import type { GraphQLSchemaDefinition } from "@webiny/handler-graphql/types.js";

const TYPE_MAP: Record<string, "manage" | "read"> = {
    preview: "read",
    read: "read",
    manage: "manage"
};

interface CreatePluginCallableParams {
    schema: GraphQLSchemaDefinition<CmsContext>;
    type: "manage" | "preview" | "read";
    fieldType: string;
}

interface CreatePluginCallable {
    (params: CreatePluginCallableParams): IGraphQLSchemaPlugin<CmsContext>;
}

const defaultCreatePlugin: CreatePluginCallable = ({ schema, type, fieldType }) => {
    const plugin = createCmsGraphQLSchemaPlugin(schema);
    plugin.name = `headless-cms.graphql.schema.${type}.field.${fieldType}`;
    return plugin;
};

interface Params {
    models: CmsModel[];
    fieldTypePlugins: CmsFieldTypePlugins;
    type: ApiEndpoint;
    createPlugin?: CreatePluginCallable;
}
export const createGraphQLSchemaPluginFromFieldPlugins = (params: Params) => {
    const { models, fieldTypePlugins, type, createPlugin = defaultCreatePlugin } = params;

    const apiType = TYPE_MAP[type];

    const plugins: ICmsGraphQLSchemaPlugin[] = [];
    for (const key in fieldTypePlugins) {
        const fieldTypePlugin = fieldTypePlugins[key];
        if (!apiType || !fieldTypePlugin[apiType]) {
            continue;
        }
        const createSchema = fieldTypePlugin[apiType].createSchema;
        // Render gql types generated by field type plugins
        if (!createSchema) {
            continue;
        }
        const schema = createSchema({ models });

        // const plugin = createCmsGraphQLSchemaPlugin(schema);
        // plugin.name = `headless-cms.graphql.schema.${type}.field.${fieldTypePlugin.fieldType}`;
        const plugin = createPlugin({
            schema,
            type,
            fieldType: fieldTypePlugin.fieldType
        });
        plugins.push(plugin);
    }
    return plugins;
};
